home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / dev / sd.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  10KB  |  489 lines

  1.  
  2. #ifndef lint
  3. /* static  char sccsid[] = "@(#)sd.c 1.1 86/09/27 Copyr 1986 Sun Micro"; */
  4. #endif
  5.  
  6. /*
  7.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  8.  */
  9.  
  10. #include "../dev/saio.h"
  11. #include "../h/param.h"
  12. #include "../dev/dklabel.h"
  13. #include "../dev/dkio.h"
  14. #include "../h/buf.h"
  15. #include "../dev/screg.h"
  16. #include "../dev/sireg.h"
  17. #include "../dev/scsi.h"
  18. #include "../h/sunromvec.h"
  19. #include "../h/idprom.h"
  20.  
  21. /* For RAM-based code, print detailed error messages */
  22. #if !defined(SDBOOT) && !defined(BOOTBLOCK) && DEBUG
  23. #define SDERRORS
  24. #endif
  25. #define SECSIZE  512
  26. #define MAXBSIZE 8192
  27.  
  28. #define NSD    1
  29. unsigned long sdaddrs[NSD] = { 0x0, };
  30.  
  31. /*
  32.  * Scsi disk parameter block
  33.  */
  34. struct sdparam {
  35.     int    sd_target;
  36.     int    sd_unit;
  37.     int    sd_boff;
  38. #ifdef SUN3
  39.     int    sd_ha_type;
  40. #endif
  41.     struct saioreq subsip[1];    /* Sip for host adapter */
  42. };
  43.  
  44. /*
  45.  * Record an error message from scsi
  46.  */
  47. #define DEBUG FIXME
  48.  
  49. #if (!defined(SDBOOT)) & !defined(STBOOT) & !defined(DEBUG)
  50.  
  51. #define    sc_error(msg)    scerrmsg = msg
  52. #define DEFERRED_ERRORS
  53. extern char *scerrmsg;
  54.  
  55. #else
  56.  
  57. extern sc_error();    /* It's in sc.c */
  58. #undef DEFERRED_ERRORS
  59.  
  60. #endif
  61.  
  62. /*
  63.  * Our DMA space
  64.  */
  65. struct sddma {
  66.     char    buffer[MAXBSIZE];
  67.     struct dk_label xlabel[1];
  68. };
  69.  
  70. #define SDBUF        (((struct sddma *)sip->si_dmaaddr)->buffer)
  71. #define label        (((struct sddma *)sip->si_dmaaddr)->xlabel)
  72.  
  73. /*
  74.  * What resources we need to run
  75.  */
  76. struct devinfo sdinfo = {
  77.     0,                /* No device to map in */
  78.     sizeof (struct sddma),
  79.     sizeof (struct sdparam),
  80.     NSD,                /* Dummy devices */
  81.     sdaddrs,            /* Dummy devices */
  82.     MAP_MAINMEM,
  83.     MAXBSIZE,            /* transfer size */
  84. };
  85.  
  86. /*
  87.  * The interfaces we export
  88.  */
  89. extern int xxprobe(), xxboot();
  90. int sdopen(), sdclose(), sdstrategy();
  91.  
  92. struct boottab sddriver = {
  93.     "sd",    xxprobe, xxboot,
  94.      sdopen, sdclose, sdstrategy,
  95.     "sd: Adaptec SCSI disk", &sdinfo
  96. };
  97.  
  98. #ifndef BOOTBLOCK
  99.  
  100. /*
  101.  * Test routine for isspinning() to see if SCSI disk is running.
  102.  */
  103. sdspin(sip, dummy)
  104.     struct saioreq *sip;
  105.     int dummy;
  106. {
  107.     int    retval;
  108. #ifdef lint
  109.     dummy = dummy;
  110. #endif lint
  111.     sip->si_bn = 0;
  112.     sip->si_cc = 0;
  113.     sip->si_ma = 0;
  114.     retval = sdcmd(SC_TEST_UNIT_READY, sip, 0);
  115.     /* some esdi controllers need to be told twice.. */
  116.         return (retval <= 0 ? sdcmd(SC_TEST_UNIT_READY, sip, 0) : retval);
  117. }
  118. #endif
  119.  
  120. #ifdef SUN3
  121. /*
  122.  * Determine type of host adaptor interface, si or sc.
  123.  * Returns 1 if si host adaptor and 0 if sc host adaptor.
  124.  */
  125. sd_probe(sip)
  126.     struct saioreq *sip;
  127. {
  128.     if (siprobe(sip)) {
  129.         return (1);
  130.     } else {
  131.         return (0);
  132.     }
  133. }
  134. #endif
  135.  
  136. /*
  137.  * Open the SCSI Disk controller
  138.  */
  139. sdopen(sip)
  140.     register struct saioreq *sip;
  141. {
  142.     register struct sdparam *sdp;
  143.     register short *sp, sum;
  144.     register int count, r;
  145.  
  146.     sdp = (struct sdparam *)sip->si_devdata;
  147.     bzero( (char *)sdp, (sizeof (struct sdparam)));
  148.  
  149.     /*
  150.      * Open the host adapter
  151.      */
  152.     *sdp->subsip = *sip;        /* Initialize sub-sip */
  153. #ifdef SUN3
  154.     {
  155.         extern struct boottab scdriver;
  156.         extern struct boottab sidriver;
  157.  
  158.         /* FIXME, find out which scsi interface to use */
  159.         if (sd_probe(sip)) {
  160.             sdp->sd_ha_type = 1;
  161.  
  162.             /* FIXME, must vector thru table */
  163.             sdp->subsip->si_boottab = &sidriver;    
  164.         } else {
  165.             sdp->sd_ha_type = 0;
  166.  
  167.             /* FIXME, must vector thru table */
  168.             sdp->subsip->si_boottab = &scdriver;    
  169.         }
  170.  
  171.     }
  172. #endif
  173. #ifdef SUN2
  174.     {
  175.         extern struct boottab scdriver;
  176.  
  177.         sdp->subsip->si_boottab = &scdriver;    
  178.     }
  179. #endif
  180.     sdp->subsip->si_unit = sip->si_unit >> 2;    /* Target number */
  181.     r = devopen(sdp->subsip);
  182.     if (r < 0) return r;
  183.  
  184.     sdp->sd_unit = sip->si_unit & 0x03;    /* Logical unit number */
  185.  
  186. #ifndef BOOTBLOCK
  187.     /*
  188.      * Check that the disk is up and running...
  189.      */
  190.     switch (isspinning(sdspin, (char *)sip, 0)) {
  191.  
  192.     default:    /* Error from sdspin */
  193.     case 0:        /* Disk still not ready */
  194.         /* isspinning has already printed "Giving up..." */
  195.         return (-1);
  196.  
  197.     case 1:
  198.         break;
  199.  
  200.     case 2:
  201.         DELAY(1000000);  /* one second delay after spinup */
  202.         break;
  203.     }
  204. #endif
  205.  
  206.     /*
  207.      * Actually read the label
  208.      */
  209.     label->dkl_magic = 0;
  210.     sip->si_ma = (char *)label;
  211.     sip->si_cc = SECSIZE;
  212.     sip->si_bn = 0;        /* Read block #0 */
  213.     if (sdcmd(SC_READ, sip, 1) <= 0) {
  214.         return (-1);
  215.     }
  216.     if (chklabel(label)) {
  217.         return -1;
  218.     }
  219.     sdp->sd_boff = (unsigned short)(label->dkl_map[sip->si_boff].dkl_cylno)
  220.         * (unsigned short)(label->dkl_nhead * label->dkl_nsect);
  221.     return (0);
  222. }
  223.  
  224. /*
  225.  * Execute reads or writes for the outside world.
  226.  */
  227. sdstrategy(sip, rw)
  228.     struct saioreq *sip;
  229.     register int rw;
  230. {
  231.     rw = sdcmd(rw == WRITE ? SC_WRITE : SC_READ, sip, 1);
  232.     if (rw < 0)
  233.         rw = 0;
  234.     return rw;
  235. }
  236.  
  237. /*
  238.  * Internal interface to the disk command set
  239.  *
  240.  * Returns the character count read (or 1 if count==0) for success,
  241.  * returns 0 for failure, or -1 for severe unretryable failure.
  242.  */
  243. int
  244. sdcmd(cmd, sip, errprint)
  245.     int cmd;
  246.     register struct saioreq *sip;
  247.     int errprint;
  248. {
  249.     int blkno, acount;
  250.     register char *buf;
  251.     register struct sdparam *sdp;
  252.     struct scsi_cdb cdb, scdb;
  253.     struct scsi_scb scb, sscb;
  254.     register int retry, r, i, count;
  255.  
  256.     blkno = sip->si_bn;
  257.     acount = sip->si_cc;
  258.     buf = sip->si_ma;
  259.     sdp = (struct sdparam *)sip->si_devdata;
  260.  
  261.     if (cmd == SC_WRITE)
  262.         bcopy(buf, SDBUF, (unsigned)acount);
  263.  
  264.     /* set up cdb */
  265.     bzero((char *) &cdb, sizeof cdb);
  266.     cdb.cmd = cmd;
  267.     cdb.lun = sdp->sd_unit;
  268.     blkno += sdp->sd_boff;
  269.     cdbaddr(&cdb, blkno);
  270.     count = (acount + SECSIZE -1) & ~(SECSIZE-1);
  271.     cdb.count = count / SECSIZE;
  272.     retry = 0;
  273.     do {
  274.         sdp->subsip->si_cc = count;
  275.         sdp->subsip->si_ma = SDBUF;
  276. #ifdef SUN3
  277.         if (sdp->sd_ha_type)
  278.             r = sidoit(&cdb, &scb, sdp->subsip);
  279.         else
  280. #endif
  281.             r = scdoit(&cdb, &scb, sdp->subsip);
  282.         if (r < 0) 
  283.             return -1; /* Major SCSI bus error, already printed */
  284.         if (scb.chk) {
  285.             bzero((char *) &scdb, sizeof scdb);
  286.             scdb.cmd = SC_REQUEST_SENSE;
  287.             scdb.lun = sdp->sd_unit;
  288.             scdb.count = sizeof (struct scsi_sense);
  289.             sdp->subsip->si_cc = scdb.count;
  290.             sdp->subsip->si_ma = SDBUF;
  291. #ifdef SUN3
  292.             if (sdp->sd_ha_type)
  293.                 i = sidoit(&scdb, &sscb, sdp->subsip);
  294.             else
  295. #endif
  296.                 i = scdoit(&scdb, &sscb, sdp->subsip);
  297.             if (i >= 4) {    /* all the sense Adaptec gives us */
  298. #ifndef DEFERRED_ERRORS
  299.                 if (errprint) sd_pr_sense(SDBUF, i);
  300. #endif
  301.                 continue;
  302.             } else {    /* can't get sense, give up */
  303.                 if (errprint) {
  304.                     printf("sd: scsi %s\n",
  305. #ifdef DEFERRED_ERRORS
  306.                     scerrmsg ? scerrmsg :
  307. #endif
  308.                     "sense failed");
  309.                 }
  310.                 return (0);
  311.             }
  312.         } else if (scb.busy) {
  313.             sc_error("disk busy");
  314.             DELAY(100000);
  315.             continue;
  316.         }
  317.         if (r != count) {
  318. #ifndef DEFERRED_ERRORS
  319.             if (errprint)
  320.                 printf("sd: dma count is %d wanted %d\n",
  321.                     r, count);
  322. #endif
  323.             continue;
  324.         }
  325.         if (cmd == SC_READ)
  326.             bcopy(SDBUF, buf, (unsigned)acount);
  327. #ifdef DEFERRED_ERRORS
  328.         scerrmsg = 0;
  329. #endif
  330.         return (count ? count : 1);
  331.     } while (retry++ < 16);
  332. #ifdef DEFERRED_ERRORS
  333.     if (errprint) {
  334.         if (scb.chk) {
  335.             sd_pr_sense(SDBUF, i);
  336.         } else if (scerrmsg) {
  337.             printf("sd: scsi %s\n", scerrmsg);
  338.         } else if (r != count) {
  339.             printf("sd: dma count is %d wanted %d\n", r, count);
  340.         } else {
  341.             /* we should never get this far */
  342.             printf("sd: retry count exceeded\n");
  343.         }
  344.     }
  345. #endif
  346.     return (0);
  347. }
  348.  
  349. #ifdef SDERRORS
  350. char    *class_00_errors[] = {
  351.     "No sense",
  352.     "No index signal",
  353.     "No seek complete",
  354.     "Write fault",
  355.     "Drive not ready",
  356.     "Drive not selected",
  357.     "No track 00",
  358.     "Multiple drives selected",
  359.     "No address acknowledged",
  360.     "Media not loaded",
  361.     "Insufficient capacity",
  362. };
  363.  
  364. char    *class_01_errors[] = {
  365.     "I.D. CRC error",
  366.     "Unrecoverable data error",
  367.     "I.D. address mark not found",
  368.     "Data address mark not found",
  369.     "Record not found",
  370.     "Seek error",
  371.     "DMA timeout error",
  372.     "Write protected",
  373.     "Correctable data check",
  374.     "Bad block found",
  375.     "Interleave error",
  376.     "Data transfer incomplete",
  377.     "Unformatted or bad format on drive",
  378.     "Self test failed",
  379.     "Defective track (media errors)",
  380. };
  381.  
  382. char    *class_02_errors[] = {
  383.     "Invalid command",
  384.     "Illegal block address",
  385.     "Aborted",
  386.     "Volume overflow",
  387. };
  388.  
  389. char    **sc_errors[] = {
  390.     class_00_errors,
  391.     class_01_errors,
  392.     class_02_errors,
  393.     0, 0, 0, 0,
  394. };
  395.  
  396. int    sc_errct[] = {
  397.     sizeof class_00_errors / sizeof (char *),
  398.     sizeof class_01_errors / sizeof (char *),
  399.     sizeof class_02_errors / sizeof (char *),
  400.     0, 0, 0, 0,
  401. };
  402.  
  403. char    *sc_sense7_keys [] = {
  404.     "No sense",
  405.     "Recoverable error",
  406.     "Not ready",
  407.     "Media error",
  408.     "Hardware error",
  409.     "Illegal request",
  410.     "Media change",
  411.     "Write protect",
  412.     "Diagnostic unique",
  413.     "Vendor unique",
  414.     "Power up failed",
  415.     "Aborted command",
  416.     "Equal",
  417.     "Volume overflow",
  418. };
  419. #endif SDERRORS
  420.  
  421. /*
  422.  * Print out sense info.
  423.  */
  424. sd_pr_sense(sp, len)
  425.     register unsigned char *sp;
  426.     register int len;
  427. {
  428.  
  429. #ifndef SDERRORS
  430.     printf("sd: error");
  431.     while (--len >= 0) {
  432.         printf(" %x", *sp++);
  433.     }
  434.     printf("\n");
  435. #else  SDERRORS
  436. #ifdef lint
  437.     len = len;    /* Avoid spurious "len unused" messages */
  438. #endif lint
  439.     printf("sd: ");
  440.     if (((struct scsi_sense *)sp)->class <= 6) {
  441.         register struct scsi_sense *sense;
  442.  
  443.         sense = (struct scsi_sense *) sp;
  444.         if (sense->code < sc_errct[sense->class]) {
  445.             printf("%s", sc_errors[sense->class][sense->code]);
  446.         } else {
  447.             printf("error %x", *sp);
  448.         }
  449.         if (sense->adr_val) {
  450.             printf("- block no. %d", (sense->high_addr << 16) |
  451.                 (sense->mid_addr << 8) | sense->low_addr);
  452.         }
  453.     } else {    /* Sense class 7: the standardized one */
  454.         register struct scsi_ext_sense *sense7;
  455.  
  456.         sense7 = (struct scsi_ext_sense *) sp;
  457.         if (sense7->fil_mk) {
  458.             printf("file mark ");
  459.         }
  460.         if (sense7->eom) {
  461.             printf("end of medium ");
  462.         }
  463.         if (sense7->key 
  464.             < sizeof (sc_sense7_keys) / sizeof (sc_sense7_keys[0])) {
  465.             printf("%s", sc_sense7_keys[sense7->key]);
  466.         } else {
  467.             printf("sense key %x", sense7->key);
  468.         }
  469.         printf(" block no. %x", (sense7->info_1 << 24) |
  470.             (sense7->info_2 << 16) | (sense7->info_3 << 8) |
  471.             sense7->info_4);
  472.     }
  473.     printf("\n");
  474. #endif SDERRORS
  475. }
  476.  
  477.  
  478. /*
  479.  * Close scsi disk
  480.  *
  481.  * We must close the host adapter too.
  482.  */
  483. int
  484. sdclose(sip)
  485.     struct saioreq *sip;
  486. {
  487.     devclose(((struct sdparam *)sip->si_devdata)->subsip);
  488. }
  489.